package game

import (
	"fmt"
	"gamesdk/inter"
	"gamesdk/wanyu/server/engine/wplog"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
	"gamesdk/wanyu/server/api/gameapi/gameframe"
	"gamesdk/wanyu/server/api/gameapi/games/ddz/common"
	"gamesdk/wanyu/server/api/gameapi/games/ddz/logic"
	"gamesdk/wanyu/server/protogo/gameddz"


)

//是否是测试模式
var isTest bool = false

//连续超时一定次数就托管
const maxTimeOutCnt int = 1

//玩家操作来源
type playerOpOrigin int

const (
	//OrgCLIENT 客户端或者机器人
	OrgCLIENT playerOpOrigin = iota
	//OrgSERVER 服务端本身
	OrgSERVER
	//OrgGAMETIMEOUT 游戏定时器超时或者玩家操作定时器超时
	OrgGAMETIMEOUT
	//OrgTRUSTEEETIMEOUT 托管定时器超时
	OrgTRUSTEEETIMEOUT
)

//出牌数据
type outData struct {
	//当前出牌回合, 从0开始递增
	round int32
	//玩家当前回合出牌类型
	option gameddz.OptionType
	//玩家当前回合出牌数据
	cards []logic.Card
}

//玩家数据
type playerData struct {
	//玩家是否托管
	isTrust bool
	//玩家是否继续游戏
	isContinue bool
	//玩家操作是否回应
	resp bool
	//玩家叫地主类型
	//calltype gameddz.CallBankerType
	call bool
	//玩家倍数（玩家选择加倍）--- 0:还未进行加倍，1:不加倍，2:加倍
	multi int32
	md int32
	//玩家手牌
	handCards []logic.Card
	//玩家出牌数据
	outCards []*outData
	//玩家出牌次数, 用于统计春天，反春
	outCount int32
	//玩家起始金额
	beginMoney int64
	//玩家游戏输赢
	winMoney int64
	//玩家税收
	tax int64
	//玩家操作定时器id
	timerID int
	//玩家托管定时器id
	trustTimerID int
	//玩家出牌超时连续次数
	timeOutCnt int

	callChoose int
	robChoose  int
	moneyChange int64
}
//游戏当前状态
type GameState int32
const (
	//等待状态
	GameState_WAIT GameState = 0
	//就绪状态
	GameState_READY GameState = 1
	//游戏中
	GameState_GAMING GameState = 2
)

//斗地主游戏类
type DdzGame struct {
	Table inter.TableInter
	GameState gamebase.GameState

	//框架接口，
	r wanju_gameframe.Room
	//游戏配置
	gameCfg *common.GameCfg
	//游戏步骤
	gameStep gameddz.GameStep
	//游戏定时器
	timerID int
	//庄家（地主）
	banker    wanju_gameframe.Player
	prebanker wanju_gameframe.Player
	//当前操作玩家
	curOper wanju_gameframe.Player
	//第一个叫地主玩家
	firstCall wanju_gameframe.Player
	//当前回合第一个出牌玩家
	firstOuter wanju_gameframe.Player
	//当前最大叫地主倍数（不叫，1分，2分，3分）
	//maxCallType gameddz.CallBankerType
	//当前回合最大出牌玩家
	maxOutPlayer wanju_gameframe.Player
	//当前回合最大出牌牌组
	maxOutCards []logic.Card
	//地主三张牌
	threeCards []logic.Card
	//游戏倍数（游戏过程中产生的倍数，例如炸弹，春天）
	gameMulti int32
	//当前出牌回合, 从0开始递增
	round int32
	//玩家数据
	playersData []*playerData
	//游戏步骤开始时间
	beginTime time.Time
	//是否是玩家打出王炸的出牌回合
	isOutRocket bool
	//是否受控
	isCtrl bool
	//杀放概率
	killRate float32
	//控制类型
	ctrlType wanju_gameframe.CtrlType

	multiDetail  map[int]*multiDetailInfo
	superDouble  bool
	shuffleTimes int

	outCards map[int][]logic.Card
}
func (g *DdzGame) earlyBankerSeat() int {
	if g.banker != nil {
		bankerSeat := g.banker.GetInfo().Seat
		if bankerSeat == 0 {
			return 2
		} else {
			return bankerSeat - 1
		}
	}
	return -1
}
func (g *DdzGame) lateBankerSeat() int {
	if g.banker != nil {
		bankerSeat := g.banker.GetInfo().Seat
		return (bankerSeat+1) % 3
	}
	return -1
}
func (g *DdzGame) robCount() int {
	sum := 0
	for i := 0; i < 3; i++ {
		if g.playersData[i].robChoose != 0 {
			sum++
		}
	}
	return sum
}
func (g *DdzGame) findNextSeatCanRob(seat int) int {
	if g.robCount() == 2 {
		for i := 0; i < 3; i++ {
			if g.playersData[i].callChoose == 1 {
				return i
			}
		}
	}
	if g.playersData[(seat+1)%3].callChoose == 0 {
		return (seat + 1) % 3
	}
	if g.playersData[(seat+2)%3].callChoose == 0 {
		return (seat + 2) % 3
	}
	panic("impossible")
}

func (g *DdzGame) robStageFinish() bool {
	negativeCount := 0
	negativeSeat := 0
	for i := 0; i < 3; i++ {
		if g.playersData[i].robChoose == -1 {
			negativeCount++
			negativeSeat = i
		}
	}
	if negativeCount == 2 {
		return true
	} else if negativeCount == 1 {
		c1 := g.playersData[(negativeSeat+1)%3].robChoose
		c2 := g.playersData[(negativeSeat+2)%3].robChoose
		if c1+c2 == 2 { // 1,1
			return true
		} else if c1+c2 == 1 { //0,1 or 1,0
			return false
		} else { // 0,0
			return false
		}
	} else { // negativeCount == 0
		sum := 0
		for i := 0; i < 3; i++ {
			sum += g.playersData[i].robChoose
		}
		if sum == 3 {
			return true
		} else {
			return false
		}
	}
}

type multiDetailInfo struct {
	//multi int
	//seatId int

	multi [3]int
}
// CreateGame 创建游戏
func CreDateGame(r gameframe.Room) gameframe.Game {
	gCfg, kCfg, exgCfg, exkCfg := r.GetGameCfg()
	g := &dzGame{
		r:            r,
		gameCfg:      &common.GameCfg{GameCfg: gCfg, KindCfg: kCfg, ExGameCfg: exgCfg.(*gameddz.GameExCfg), ExKindCfg: exkCfg.(*gameddz.KindExCfg)},
		gameStep:     gameddz.GameStep_ST_WAITING_START,
		timerID:      -1,
		banker:       nil,
		prebanker:    nil,
		curOper:      nil,
		firstCall:    nil,
		firstOuter:   nil,
		maxOutPlayer: nil,
		maxOutCards:  nil,
		threeCards:   nil,
		gameMulti:    1,
		round:        0,
		isOutRocket:  false,
		playersData:  make([]*playerData, gCfg.MaxPlayerCnt),
		multiDetail:  make(map[int]*multiDetailInfo, int(gameddz.MultiChangeInform_ALL)),
		players:	make(map[string] *player.Player),
		outCards:	make(map[int][]logic.Card),
	}
	g.gameCfg.GameStartAni = 1000
	g.gameCfg.SendCardAni = 2700
	g.gameCfg.EnsureBankerAni = 700
	g.gameCfg.WaitEndAni = 2000
	g.gameCfg.GameEndAni = 3000

	//初始化游戲時間
	g.gameCfg.ExGameCfg.CallBankerDur = 15
	g.gameCfg.ExGameCfg.PlayerDoubleDur = 10
	g.gameCfg.ExGameCfg.OutCardDur = 25
	g.gameCfg.ExGameCfg.GameEndDur = 10
	g.gameCfg.ExGameCfg.RobBankerDur = 15
	g.gameCfg.ExGameCfg.CanNotFollow = 3

	for i := 0; i < int(gameddz.MultiChangeInform_ALL); i++ {
		if i == int(gameddz.MultiChangeInform_INIT) {
			g.multiDetail[i] = &multiDetailInfo{[3]int{int(g.gameCfg.KindCfg.BaseMultiple), 1, 1}}
		} else {
			g.multiDetail[i] = &multiDetailInfo{[3]int{1, 1, 1}}
		}
	}
	g.gameCfg.AnnouncementCfg = LoadAnnoucCfg("announcement_config.yaml", g.gameCfg.KindCfg.KindId)

	return g
}
func LoadAnnoucCfg(configfile string, kindId uint32) map[string][]int64 {

	tempResult := make(map[string]map[uint32]map[string][]int64)
	// 执行解析
	ex, err := os.Executable()
	if err != nil {
		wplog.Errorf("get binary file path failed: %v", err)
	}

	data, err := ioutil.ReadFile(filepath.Dir(ex) + fmt.Sprintf("%c", os.PathSeparator) + configfile)
	if err != nil {
		wplog.Errorf("yamlFile.Get err   #%v ", err)
	}
	err = yaml.Unmarshal(data, &tempResult)
	if err != nil {
		wplog.Errorf(" yaml unmarshal error: %v", err)
	}
	if result, ok := tempResult["ddz"][kindId]; ok {
		return result
	} else {
		wplog.Errorf("get annoucCfg error: %v", err)
		return nil
	}
	//if ok != nil {
	//	wplog.Errorf("get annoucCfg error: %v", err)
	//}
	//return result,err
}


